home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / WarpQuake / Src / gl_rmain.c < prev    next >
C/C++ Source or Header  |  2000-05-22  |  26KB  |  1,160 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // r_main.c
  21.  
  22. #include "quakedef.h"
  23.  
  24. entity_t    r_worldentity;
  25.  
  26. qboolean    r_cache_thrash;        // compatability
  27.  
  28. vec3_t        modelorg, r_entorigin;
  29. entity_t    *currententity;
  30.  
  31. int            r_visframecount;    // bumped when going to a new PVS
  32. int            r_framecount;        // used for dlight push checking
  33.  
  34. mplane_t    frustum[4];
  35.  
  36. int            c_brush_polys, c_alias_polys;
  37.  
  38. qboolean    envmap;                // true during envmap command capture 
  39.  
  40. int            currenttexture = -1;        // to avoid unnecessary texture sets
  41.  
  42. int            cnttextures[2] = {-1, -1};     // cached
  43.  
  44. int            particletexture;    // little dot for particles
  45. int            playertextures;        // up to 16 color translated skins
  46.  
  47. int            mirrortexturenum;    // quake texturenum, not gltexturenum
  48. qboolean    mirror;
  49. mplane_t    *mirror_plane;
  50.  
  51. //
  52. // view origin
  53. //
  54. vec3_t    vup;
  55. vec3_t    vpn;
  56. vec3_t    vright;
  57. vec3_t    r_origin;
  58.  
  59. float    r_world_matrix[16];
  60. float    r_base_world_matrix[16];
  61.  
  62. //
  63. // screen size info
  64. //
  65. refdef_t    r_refdef;
  66.  
  67. mleaf_t        *r_viewleaf, *r_oldviewleaf;
  68.  
  69. texture_t    *r_notexture_mip;
  70.  
  71. int        d_lightstylevalue[256];    // 8.8 fraction of base light value
  72.  
  73.  
  74. void R_MarkLeaves (void);
  75.  
  76. cvar_t    r_norefresh = {"r_norefresh","0"};
  77. cvar_t    r_drawentities = {"r_drawentities","1"};
  78. cvar_t    r_drawviewmodel = {"r_drawviewmodel","1"};
  79. cvar_t    r_speeds = {"r_speeds","0"};
  80. cvar_t    r_fullbright = {"r_fullbright","0"};
  81. cvar_t    r_lightmap = {"r_lightmap","0"};
  82. cvar_t    r_shadows = {"r_shadows","0"};
  83. cvar_t    r_mirroralpha = {"r_mirroralpha","1"};
  84. cvar_t    r_wateralpha = {"r_wateralpha","1"};
  85. cvar_t    r_dynamic = {"r_dynamic","1"};
  86. cvar_t    r_novis = {"r_novis","0"};
  87.  
  88. cvar_t    gl_finish = {"gl_finish","0"};
  89. cvar_t    gl_clear = {"gl_clear","0"};
  90. cvar_t    gl_cull = {"gl_cull","1"};
  91. cvar_t    gl_texsort = {"gl_texsort","1"};
  92. cvar_t    gl_smoothmodels = {"gl_smoothmodels","1"};
  93. cvar_t    gl_affinemodels = {"gl_affinemodels","0"};
  94. cvar_t    gl_polyblend = {"gl_polyblend","1"};
  95. cvar_t    gl_flashblend = {"gl_flashblend","1"};
  96. cvar_t    gl_playermip = {"gl_playermip","0"};
  97. cvar_t    gl_nocolors = {"gl_nocolors","0"};
  98. cvar_t    gl_keeptjunctions = {"gl_keeptjunctions","0"};
  99. cvar_t    gl_reporttjunctions = {"gl_reporttjunctions","0"};
  100. cvar_t    gl_doubleeyes = {"gl_doubleeys", "1"};
  101.  
  102. extern    cvar_t    gl_ztrick;
  103.  
  104. /*
  105. =================
  106. R_CullBox
  107.  
  108. Returns true if the box is completely outside the frustom
  109. =================
  110. */
  111. qboolean R_CullBox (vec3_t mins, vec3_t maxs)
  112. {
  113.     int        i;
  114.  
  115.     for (i=0 ; i<4 ; i++)
  116.         if (BoxOnPlaneSide (mins, maxs, &frustum[i]) == 2)
  117.             return true;
  118.     return false;
  119. }
  120.  
  121.  
  122. void R_RotateForEntity (entity_t *e)
  123. {
  124.     glTranslatef (e->origin[0],  e->origin[1],  e->origin[2]);
  125.  
  126.     glRotatef (e->angles[1],  0, 0, 1);
  127.     glRotatef (-e->angles[0],  0, 1, 0);
  128.     glRotatef (e->angles[2],  1, 0, 0);
  129. }
  130.  
  131. /*
  132. =============================================================
  133.  
  134.   SPRITE MODELS
  135.  
  136. =============================================================
  137. */
  138.  
  139. /*
  140. ================
  141. R_GetSpriteFrame
  142. ================
  143. */
  144. mspriteframe_t *R_GetSpriteFrame (entity_t *currententity)
  145. {
  146.     msprite_t        *psprite;
  147.     mspritegroup_t    *pspritegroup;
  148.     mspriteframe_t    *pspriteframe;
  149.     int                i, numframes, frame;
  150.     float            *pintervals, fullinterval, targettime, time;
  151.  
  152.     psprite = currententity->model->cache.data;
  153.     frame = currententity->frame;
  154.  
  155.     if ((frame >= psprite->numframes) || (frame < 0))
  156.     {
  157.         Con_Printf ("R_DrawSprite: no such frame %d\n", frame);
  158.         frame = 0;
  159.     }
  160.  
  161.     if (psprite->frames[frame].type == SPR_SINGLE)
  162.     {
  163.         pspriteframe = psprite->frames[frame].frameptr;
  164.     }
  165.     else
  166.     {
  167.         pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr;
  168.         pintervals = pspritegroup->intervals;
  169.         numframes = pspritegroup->numframes;
  170.         fullinterval = pintervals[numframes-1];
  171.  
  172.         time = cl.time + currententity->syncbase;
  173.  
  174.     // when loading in Mod_LoadSpriteGroup, we guaranteed all interval values
  175.     // are positive, so we don't have to worry about division by 0
  176.         targettime = time - ((int)(time / fullinterval)) * fullinterval;
  177.  
  178.         for (i=0 ; i<(numframes-1) ; i++)
  179.         {
  180.             if (pintervals[i] > targettime)
  181.                 break;
  182.         }
  183.  
  184.         pspriteframe = pspritegroup->frames[i];
  185.     }
  186.  
  187.     return pspriteframe;
  188. }
  189.  
  190.  
  191. /*
  192. =================
  193. R_DrawSpriteModel
  194.  
  195. =================
  196. */
  197. void R_DrawSpriteModel (entity_t *e)
  198. {
  199.     vec3_t    point;
  200.     mspriteframe_t    *frame;
  201.     float        *up, *right;
  202.     vec3_t        v_forward, v_right, v_up;
  203.     msprite_t        *psprite;
  204.  
  205.     // don't even bother culling, because it's just a single
  206.     // polygon without a surface cache
  207.     frame = R_GetSpriteFrame (e);
  208.     psprite = currententity->model->cache.data;
  209.  
  210.     if (psprite->type == SPR_ORIENTED)
  211.     {    // bullet marks on walls
  212.         AngleVectors (currententity->angles, v_forward, v_right, v_up);
  213.         up = v_up;
  214.         right = v_right;
  215.     }
  216.     else
  217.     {    // normal sprite
  218.         up = vup;
  219.         right = vright;
  220.     }
  221.  
  222.     glColor3f (1,1,1);
  223.  
  224.     GL_DisableMultitexture();
  225.  
  226.     GL_Bind(frame->gl_texturenum);
  227.  
  228.     glEnable (GL_ALPHA_TEST);
  229.     glBegin (GL_QUADS);
  230.  
  231.     glTexCoord2f (0, 1);
  232.     VectorMA (e->origin, frame->down, up, point);
  233.     VectorMA (point, frame->left, right, point);
  234.     glVertex3fv (point);
  235.  
  236.     glTexCoord2f (0, 0);
  237.     VectorMA (e->origin, frame->up, up, point);
  238.     VectorMA (point, frame->left, right, point);
  239.     glVertex3fv (point);
  240.  
  241.     glTexCoord2f (1, 0);
  242.     VectorMA (e->origin, frame->up, up, point);
  243.     VectorMA (point, frame->right, right, point);
  244.     glVertex3fv (point);
  245.  
  246.     glTexCoord2f (1, 1);
  247.     VectorMA (e->origin, frame->down, up, point);
  248.     VectorMA (point, frame->right, right, point);
  249.     glVertex3fv (point);
  250.     
  251.     glEnd ();
  252.  
  253.     glDisable (GL_ALPHA_TEST);
  254. }
  255.  
  256. /*
  257. =============================================================
  258.  
  259.   ALIAS MODELS
  260.  
  261. =============================================================
  262. */
  263.  
  264.  
  265. #define NUMVERTEXNORMALS    162
  266.  
  267. float    r_avertexnormals[NUMVERTEXNORMALS][3] = {
  268. #include "anorms.h"
  269. };
  270.  
  271. vec3_t    shadevector;
  272. float    shadelight, ambientlight;
  273.  
  274. // precalculated dot products for quantized angles
  275. #define SHADEDOT_QUANT 16
  276. float    r_avertexnormal_dots[SHADEDOT_QUANT][256] =
  277. #include "anorm_dots.h"
  278. ;
  279.  
  280. float    *shadedots = r_avertexnormal_dots[0];
  281.  
  282. int    lastposenum;
  283.  
  284. /*
  285. =============
  286. GL_DrawAliasFrame
  287. =============
  288. */
  289. void GL_DrawAliasFrame (aliashdr_t *paliashdr, int posenum)
  290. {
  291.     float    s, t;
  292.     float     l;
  293.     int        i, j;
  294.     int        index;
  295.     trivertx_t    *v, *verts;
  296.     int        list;
  297.     int        *order;
  298.     vec3_t    point;
  299.     float    *normal;
  300.     int        count;
  301.  
  302. lastposenum = posenum;
  303.  
  304.     verts = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata);
  305.     verts += posenum * paliashdr->poseverts;
  306.     order = (int *)((byte *)paliashdr + paliashdr->commands);
  307.  
  308.     while (1)
  309.     {
  310.         // get the vertex count and primitive type
  311.         count = *order++;
  312.         if (!count)
  313.             break;        // done
  314.         if (count < 0)
  315.         {
  316.             count = -count;
  317.             glBegin (GL_TRIANGLE_FAN);
  318.         }
  319.         else
  320.             glBegin (GL_TRIANGLE_STRIP);
  321.  
  322.         do
  323.         {
  324.             // texture coordinates come from the draw list
  325.             glTexCoord2f (((float *)order)[0], ((float *)order)[1]);
  326.             order += 2;
  327.  
  328.             // normals and vertexes come from the frame list
  329.             l = shadedots[verts->lightnormalindex] * shadelight;
  330.             glColor3f (l, l, l);
  331.             glVertex3f (verts->v[0], verts->v[1], verts->v[2]);
  332.             verts++;
  333.         } while (--count);
  334.  
  335.         glEnd ();
  336.     }
  337. }
  338.  
  339.  
  340. /*
  341. =============
  342. GL_DrawAliasShadow
  343. =============
  344. */
  345. extern    vec3_t            lightspot;
  346.  
  347. void GL_DrawAliasShadow (aliashdr_t *paliashdr, int posenum)
  348. {
  349.     float    s, t, l;
  350.     int        i, j;
  351.     int        index;
  352.     trivertx_t    *v, *verts;
  353.     int        list;
  354.     int        *order;
  355.     vec3_t    point;
  356.     float    *normal;
  357.     float    height, lheight;
  358.     int        count;
  359.  
  360.     lheight = currententity->origin[2] - lightspot[2];
  361.  
  362.     height = 0;
  363.     verts = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata);
  364.     verts += posenum * paliashdr->poseverts;
  365.     order = (int *)((byte *)paliashdr + paliashdr->commands);
  366.  
  367.     height = -lheight + 1.0;
  368.  
  369.     while (1)
  370.     {
  371.         // get the vertex count and primitive type
  372.         count = *order++;
  373.         if (!count)
  374.             break;        // done
  375.         if (count < 0)
  376.         {
  377.             count = -count;
  378.             glBegin (GL_TRIANGLE_FAN);
  379.         }
  380.         else
  381.             glBegin (GL_TRIANGLE_STRIP);
  382.  
  383.         do
  384.         {
  385.             // texture coordinates come from the draw list
  386.             // (skipped for shadows) glTexCoord2fv ((float *)order);
  387.             order += 2;
  388.  
  389.             // normals and vertexes come from the frame list
  390.             point[0] = verts->v[0] * paliashdr->scale[0] + paliashdr->scale_origin[0];
  391.             point[1] = verts->v[1] * paliashdr->scale[1] + paliashdr->scale_origin[1];
  392.             point[2] = verts->v[2] * paliashdr->scale[2] + paliashdr->scale_origin[2];
  393.  
  394.             point[0] -= shadevector[0]*(point[2]+lheight);
  395.             point[1] -= shadevector[1]*(point[2]+lheight);
  396.             point[2] = height;
  397. //            height -= 0.001;
  398.             glVertex3fv (point);
  399.  
  400.             verts++;
  401.         } while (--count);
  402.  
  403.         glEnd ();
  404.     }    
  405. }
  406.  
  407.  
  408.  
  409. /*
  410. =================
  411. R_SetupAliasFrame
  412.  
  413. =================
  414. */
  415. void R_SetupAliasFrame (int frame, aliashdr_t *paliashdr)
  416. {
  417.     int                pose, numposes;
  418.     float            interval;
  419.  
  420.     if ((frame >= paliashdr->numframes) || (frame < 0))
  421.     {
  422.         Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame);
  423.         frame = 0;
  424.     }
  425.  
  426.     pose = paliashdr->frames[frame].firstpose;
  427.     numposes = paliashdr->frames[frame].numposes;
  428.  
  429.     if (numposes > 1)
  430.     {
  431.         interval = paliashdr->frames[frame].interval;
  432.         pose += (int)(cl.time / interval) % numposes;
  433.     }
  434.  
  435.     GL_DrawAliasFrame (paliashdr, pose);
  436. }
  437.  
  438.  
  439.  
  440. /*
  441. =================
  442. R_DrawAliasModel
  443.  
  444. =================
  445. */
  446. void R_DrawAliasModel (entity_t *e)
  447. {
  448.     int            i, j;
  449.     int            lnum;
  450.     vec3_t        dist;
  451.     float        add;
  452.     model_t        *clmodel;
  453.     vec3_t        mins, maxs;
  454.     aliashdr_t    *paliashdr;
  455.     trivertx_t    *verts, *v;
  456.     int            index;
  457.     float        s, t, an;
  458.     int            anim;
  459.  
  460.     clmodel = currententity->model;
  461.  
  462.     VectorAdd (currententity->origin, clmodel->mins, mins);
  463.     VectorAdd (currententity->origin, clmodel->maxs, maxs);
  464.  
  465.     if (R_CullBox (mins, maxs))
  466.         return;
  467.  
  468.  
  469.     VectorCopy (currententity->origin, r_entorigin);
  470.     VectorSubtract (r_origin, r_entorigin, modelorg);
  471.  
  472.     //
  473.     // get lighting information
  474.     //
  475.  
  476.     ambientlight = shadelight = R_LightPoint (currententity->origin);
  477.  
  478.     // allways give the gun some light
  479.     if (e == &cl.viewent && ambientlight < 24)
  480.         ambientlight = shadelight = 24;
  481.  
  482.     for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
  483.     {
  484.         if (cl_dlights[lnum].die >= cl.time)
  485.         {
  486.             VectorSubtract (currententity->origin,
  487.                             cl_dlights[lnum].origin,
  488.                             dist);
  489.             add = cl_dlights[lnum].radius - Length(dist);
  490.  
  491.             if (add > 0) {
  492.                 ambientlight += add;
  493.                 //ZOID models should be affected by dlights as well
  494.                 shadelight += add;
  495.             }
  496.         }
  497.     }
  498.  
  499.     // clamp lighting so it doesn't overbright as much
  500.     if (ambientlight > 128)
  501.         ambientlight = 128;
  502.     if (ambientlight + shadelight > 192)
  503.         shadelight = 192 - ambientlight;
  504.  
  505.     // ZOID: never allow players to go totally black
  506.     i = currententity - cl_entities;
  507.     if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */)
  508.         if (ambientlight < 8)
  509.             ambientlight = shadelight = 8;
  510.  
  511.     // HACK HACK HACK -- no fullbright colors, so make torches full light
  512.     if (!strcmp (clmodel->name, "progs/flame2.mdl")
  513.         || !strcmp (clmodel->name, "progs/flame.mdl") )
  514.         ambientlight = shadelight = 256;
  515.  
  516.     shadedots = r_avertexnormal_dots[((int)(e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];
  517.     shadelight = shadelight / 200.0;
  518.     
  519.     an = e->angles[1]/180*M_PI;
  520.     shadevector[0] = cos(-an);
  521.     shadevector[1] = sin(-an);
  522.     shadevector[2] = 1;
  523.     VectorNormalize (shadevector);
  524.  
  525.     //
  526.     // locate the proper data
  527.     //
  528.     paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model);
  529.  
  530.     c_alias_polys += paliashdr->numtris;
  531.  
  532.     //
  533.     // draw all the triangles
  534.     //
  535.  
  536.     GL_DisableMultitexture();
  537.  
  538.     glPushMatrix ();
  539.     R_RotateForEntity (e);
  540.  
  541.     if (!strcmp (clmodel->name, "progs/eyes.mdl") && gl_doubleeyes.value) {
  542.         glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2] - (22 + 8));
  543. // double size of eyes, since they are really hard to see in gl
  544.         glScalef (paliashdr->scale[0]*2, paliashdr->scale[1]*2, paliashdr->scale[2]*2);
  545.     } else {
  546.         glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]);
  547.         glScalef (paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]);
  548.     }
  549.  
  550.     anim = (int)(cl.time*10) & 3;
  551.     GL_Bind(paliashdr->gl_texturenum[currententity->skinnum][anim]);
  552.  
  553.     // we can't dynamically colormap textures, so they are cached
  554.     // seperately for the players.  Heads are just uncolored.
  555.     if (currententity->colormap != vid.colormap && !gl_nocolors.value)
  556.     {
  557.         i = currententity - cl_entities;
  558.         if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */)
  559.             GL_Bind(playertextures - 1 + i);
  560.     }
  561.  
  562.     if (gl_smoothmodels.value)
  563.         glShadeModel (GL_SMOOTH);
  564.     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  565.  
  566.     if (gl_affinemodels.value)
  567.         glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
  568.  
  569.     R_SetupAliasFrame (currententity->frame, paliashdr);
  570.  
  571.     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  572.  
  573.     glShadeModel (GL_FLAT);
  574.     if (gl_affinemodels.value)
  575.         glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  576.  
  577.     glPopMatrix ();
  578.  
  579.     if (r_shadows.value)
  580.     {
  581.         glPushMatrix ();
  582.         R_RotateForEntity (e);
  583.         glDisable (GL_TEXTURE_2D);
  584.         glEnable (GL_BLEND);
  585.         glColor4f (0,0,0,0.5);
  586.         GL_DrawAliasShadow (paliashdr, lastposenum);
  587.         glEnable (GL_TEXTURE_2D);
  588.         glDisable (GL_BLEND);
  589.         glColor4f (1,1,1,1);
  590.         glPopMatrix ();
  591.     }
  592.  
  593. }
  594.  
  595. //==================================================================================
  596.  
  597. /*
  598. =============
  599. R_DrawEntitiesOnList
  600. =============
  601. */
  602. void R_DrawEntitiesOnList (void)
  603. {
  604.     int        i;
  605.  
  606.     if (!r_drawentities.value)
  607.         return;
  608.  
  609.     // draw sprites seperately, because of alpha blending
  610.     for (i=0 ; i<cl_numvisedicts ; i++)
  611.     {
  612.         currententity = cl_visedicts[i];
  613.  
  614.         switch (currententity->model->type)
  615.         {
  616.         case mod_alias:
  617.             R_DrawAliasModel (currententity);
  618.             break;
  619.  
  620.         case mod_brush:
  621.             R_DrawBrushModel (currententity);
  622.             break;
  623.  
  624.         default:
  625.             break;
  626.         }
  627.     }
  628.  
  629.     for (i=0 ; i<cl_numvisedicts ; i++)
  630.     {
  631.         currententity = cl_visedicts[i];
  632.  
  633.         switch (currententity->model->type)
  634.         {
  635.         case mod_sprite:
  636.             R_DrawSpriteModel (currententity);
  637.             break;
  638.         }
  639.     }
  640. }
  641.  
  642. /*
  643. =============
  644. R_DrawViewModel
  645. =============
  646. */
  647. void R_DrawViewModel (void)
  648. {
  649.     float        ambient[4], diffuse[4];
  650.     int            j;
  651.     int            lnum;
  652.     vec3_t        dist;
  653.     float        add;
  654.     dlight_t    *dl;
  655.     int            ambientlight, shadelight;
  656.  
  657.     if (!r_drawviewmodel.value)
  658.         return;
  659.  
  660.     if (chase_active.value)
  661.         return;
  662.  
  663.     if (envmap)
  664.         return;
  665.  
  666.     if (!r_drawentities.value)
  667.         return;
  668.  
  669.     if (cl.items & IT_INVISIBILITY)
  670.         return;
  671.  
  672.     if (cl.stats[STAT_HEALTH] <= 0)
  673.         return;
  674.  
  675.     currententity = &cl.viewent;
  676.     if (!currententity->model)
  677.         return;
  678.  
  679.     j = R_LightPoint (currententity->origin);
  680.  
  681.     if (j < 24)
  682.         j = 24;        // allways give some light on gun
  683.     ambientlight = j;
  684.     shadelight = j;
  685.  
  686. // add dynamic lights        
  687.     for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
  688.     {
  689.         dl = &cl_dlights[lnum];
  690.         if (!dl->radius)
  691.             continue;
  692.         if (!dl->radius)
  693.             continue;
  694.         if (dl->die < cl.time)
  695.             continue;
  696.  
  697.         VectorSubtract (currententity->origin, dl->origin, dist);
  698.         add = dl->radius - Length(dist);
  699.         if (add > 0)
  700.             ambientlight += add;
  701.     }
  702.  
  703.     ambient[0] = ambient[1] = ambient[2] = ambient[3] = (float)ambientlight / 128;
  704.     diffuse[0] = diffuse[1] = diffuse[2] = diffuse[3] = (float)shadelight / 128;
  705.  
  706.     // hack the depth range to prevent view model from poking into walls
  707.     glDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin));
  708.     R_DrawAliasModel (currententity);
  709.     glDepthRange (gldepthmin, gldepthmax);
  710. }
  711.  
  712.  
  713. /*
  714. ============
  715. R_PolyBlend
  716. ============
  717. */
  718. void R_PolyBlend (void)
  719. {
  720.     if (!gl_polyblend.value)
  721.         return;
  722.     if (!v_blend[3])
  723.         return;
  724.  
  725.     GL_DisableMultitexture();
  726.  
  727.     glDisable (GL_ALPHA_TEST);
  728.     glEnable (GL_BLEND);
  729.     glDisable (GL_DEPTH_TEST);
  730.     glDisable (GL_TEXTURE_2D);
  731.  
  732.     glLoadIdentity ();
  733.  
  734.     glRotatef (-90,  1, 0, 0);        // put Z going up
  735.     glRotatef (90,  0, 0, 1);        // put Z going up
  736.  
  737.     glColor4fv (v_blend);
  738.  
  739.     glBegin (GL_QUADS);
  740.  
  741.     glVertex3f (10, 100, 100);
  742.     glVertex3f (10, -100, 100);
  743.     glVertex3f (10, -100, -100);
  744.     glVertex3f (10, 100, -100);
  745.     glEnd ();
  746.  
  747.     glDisable (GL_BLEND);
  748.     glEnable (GL_TEXTURE_2D);
  749.     glEnable (GL_ALPHA_TEST);
  750. }
  751.  
  752.  
  753. int SignbitsForPlane (mplane_t *out)
  754. {
  755.     int    bits, j;
  756.  
  757.     // for fast box on planeside test
  758.  
  759.     bits = 0;
  760.     for (j=0 ; j<3 ; j++)
  761.     {
  762.         if (out->normal[j] < 0)
  763.             bits |= 1<<j;
  764.     }
  765.     return bits;
  766. }
  767.  
  768.  
  769. void R_SetFrustum (void)
  770. {
  771.     int        i;
  772.  
  773.     if (r_refdef.fov_x == 90) 
  774.     {
  775.         // front side is visible
  776.  
  777.         VectorAdd (vpn, vright, frustum[0].normal);
  778.         VectorSubtract (vpn, vright, frustum[1].normal);
  779.  
  780.         VectorAdd (vpn, vup, frustum[2].normal);
  781.         VectorSubtract (vpn, vup, frustum[3].normal);
  782.     }
  783.     else
  784.     {
  785.         // rotate VPN right by FOV_X/2 degrees
  786.         RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-r_refdef.fov_x / 2 ) );
  787.         // rotate VPN left by FOV_X/2 degrees
  788.         RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-r_refdef.fov_x / 2 );
  789.         // rotate VPN up by FOV_X/2 degrees
  790.         RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-r_refdef.fov_y / 2 );
  791.         // rotate VPN down by FOV_X/2 degrees
  792.         RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 - r_refdef.fov_y / 2 ) );
  793.     }
  794.  
  795.     for (i=0 ; i<4 ; i++)
  796.     {
  797.         frustum[i].type = PLANE_ANYZ;
  798.         frustum[i].dist = DotProduct (r_origin, frustum[i].normal);
  799.         frustum[i].signbits = SignbitsForPlane (&frustum[i]);
  800.     }
  801. }
  802.  
  803.  
  804.  
  805. /*
  806. ===============
  807. R_SetupFrame
  808. ===============
  809. */
  810. void R_SetupFrame (void)
  811. {
  812.     int                edgecount;
  813.     vrect_t            vrect;
  814.     float            w, h;
  815.  
  816. // don't allow cheats in multiplayer
  817.     if (cl.maxclients > 1)
  818.         Cvar_Set ("r_fullbright", "0");
  819.  
  820.     R_AnimateLight ();
  821.  
  822.     r_framecount++;
  823.  
  824. // build the transformation matrix for the given view angles
  825.     VectorCopy (r_refdef.vieworg, r_origin);
  826.  
  827.     AngleVectors (r_refdef.viewangles, vpn, vright, vup);
  828.  
  829. // current viewleaf
  830.     r_oldviewleaf = r_viewleaf;
  831.     r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel);
  832.  
  833.     V_SetContentsColor (r_viewleaf->contents);
  834.     V_CalcBlend ();
  835.  
  836.     r_cache_thrash = false;
  837.  
  838.     c_brush_polys = 0;
  839.     c_alias_polys = 0;
  840.  
  841. }
  842.  
  843.  
  844. void MYgluPerspective( GLdouble fovy, GLdouble aspect,
  845.              GLdouble zNear, GLdouble zFar )
  846. {
  847.    GLdouble xmin, xmax, ymin, ymax;
  848.  
  849.    ymax = zNear * tan( fovy * M_PI / 360.0 );
  850.    ymin = -ymax;
  851.  
  852.    xmin = ymin * aspect;
  853.    xmax = ymax * aspect;
  854.  
  855.    glFrustum( xmin, xmax, ymin, ymax, zNear, zFar );
  856. }
  857.  
  858.  
  859. /*
  860. =============
  861. R_SetupGL
  862. =============
  863. */
  864. void R_SetupGL (void)
  865. {
  866.     float    screenaspect;
  867.     float    yfov;
  868.     int        i;
  869.     extern    int glwidth, glheight;
  870.     int        x, x2, y2, y, w, h;
  871.  
  872.     //
  873.     // set up viewpoint
  874.     //
  875.     glMatrixMode(GL_PROJECTION);
  876.     glLoadIdentity ();
  877.     x = r_refdef.vrect.x * glwidth/vid.width;
  878.     x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * glwidth/vid.width;
  879.     y = (vid.height-r_refdef.vrect.y) * glheight/vid.height;
  880.     y2 = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)) * glheight/vid.height;
  881.  
  882.     // fudge around because of frac screen scale
  883.     if (x > 0)
  884.         x--;
  885.     if (x2 < glwidth)
  886.         x2++;
  887.     if (y2 < 0)
  888.         y2--;
  889.     if (y < glheight)
  890.         y++;
  891.  
  892.     w = x2 - x;
  893.     h = y - y2;
  894.  
  895.     if (envmap)
  896.     {
  897.         x = y2 = 0;
  898.         w = h = 256;
  899.     }
  900.  
  901.     glViewport (glx + x, gly + y2, w, h);
  902.     screenaspect = (float)r_refdef.vrect.width/r_refdef.vrect.height;
  903. //    yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*180/M_PI;
  904.     MYgluPerspective (r_refdef.fov_y,  screenaspect,  4,  4096);
  905.  
  906.     if (mirror)
  907.     {
  908.         if (mirror_plane->normal[2])
  909.             glScalef (1, -1, 1);
  910.         else
  911.             glScalef (-1, 1, 1);
  912.         glCullFace(GL_BACK);
  913.     }
  914.     else
  915.         glCullFace(GL_FRONT);
  916.  
  917.     glMatrixMode(GL_MODELVIEW);
  918.     glLoadIdentity ();
  919.  
  920.     glRotatef (-90,  1, 0, 0);        // put Z going up
  921.     glRotatef (90,  0, 0, 1);        // put Z going up
  922.     glRotatef (-r_refdef.viewangles[2],  1, 0, 0);
  923.     glRotatef (-r_refdef.viewangles[0],  0, 1, 0);
  924.     glRotatef (-r_refdef.viewangles[1],  0, 0, 1);
  925.     glTranslatef (-r_refdef.vieworg[0],  -r_refdef.vieworg[1],  -r_refdef.vieworg[2]);
  926.  
  927.     glGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix);
  928.  
  929.     //
  930.     // set drawing parms
  931.     //
  932.     if (gl_cull.value)
  933.         glEnable(GL_CULL_FACE);
  934.     else
  935.         glDisable(GL_CULL_FACE);
  936.  
  937.     glDisable(GL_BLEND);
  938.     glDisable(GL_ALPHA_TEST);
  939.     glEnable(GL_DEPTH_TEST);
  940. }
  941.  
  942. /*
  943. ================
  944. R_RenderScene
  945.  
  946. r_refdef must be set before the first call
  947. ================
  948. */
  949. void R_RenderScene (void)
  950. {
  951.     R_SetupFrame ();
  952.  
  953.     R_SetFrustum ();
  954.  
  955.     R_SetupGL ();
  956.  
  957.     R_MarkLeaves ();    // done here so we know if we're in water
  958.  
  959.     R_DrawWorld ();        // adds static entities to the list
  960.  
  961.     S_ExtraUpdate ();    // don't let sound get messed up if going slow
  962.  
  963.     R_DrawEntitiesOnList ();
  964.  
  965.     GL_DisableMultitexture();
  966.  
  967.     R_RenderDlights ();
  968.  
  969.     R_DrawParticles ();
  970.  
  971. #ifdef GLTEST
  972.     Test_Draw ();
  973. #endif
  974.  
  975. }
  976.  
  977.  
  978. /*
  979. =============
  980. R_Clear
  981. =============
  982. */
  983. void R_Clear (void)
  984. {
  985.     if (r_mirroralpha.value != 1.0)
  986.     {
  987.         if (gl_clear.value)
  988.             glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  989.         else
  990.             glClear (GL_DEPTH_BUFFER_BIT);
  991.         gldepthmin = 0;
  992.         gldepthmax = 0.5;
  993.         glDepthFunc (GL_LEQUAL);
  994.     }
  995.     else if (gl_ztrick.value)
  996.     {
  997.         static int trickframe;
  998.  
  999.         if (gl_clear.value)
  1000.             glClear (GL_COLOR_BUFFER_BIT);
  1001.  
  1002.         trickframe++;
  1003.         if (trickframe & 1)
  1004.         {
  1005.             gldepthmin = 0;
  1006.             gldepthmax = 0.49999;
  1007.             glDepthFunc (GL_LEQUAL);
  1008.         }
  1009.         else
  1010.         {
  1011.             gldepthmin = 1;
  1012.             gldepthmax = 0.5;
  1013.             glDepthFunc (GL_GEQUAL);
  1014.         }
  1015.     }
  1016.     else
  1017.     {
  1018.         if (gl_clear.value)
  1019.             glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  1020.         else
  1021.             glClear (GL_DEPTH_BUFFER_BIT);
  1022.         gldepthmin = 0;
  1023.         gldepthmax = 1;
  1024.         glDepthFunc (GL_LEQUAL);
  1025.     }
  1026.  
  1027.     glDepthRange (gldepthmin, gldepthmax);
  1028. }
  1029.  
  1030. /*
  1031. =============
  1032. R_Mirror
  1033. =============
  1034. */
  1035. void R_Mirror (void)
  1036. {
  1037.     float        d;
  1038.     msurface_t    *s;
  1039.     entity_t    *ent;
  1040.  
  1041.     if (!mirror)
  1042.         return;
  1043.  
  1044.     memcpy (r_base_world_matrix, r_world_matrix, sizeof(r_base_world_matrix));
  1045.  
  1046.     d = DotProduct (r_refdef.vieworg, mirror_plane->normal) - mirror_plane->dist;
  1047.     VectorMA (r_refdef.vieworg, -2*d, mirror_plane->normal, r_refdef.vieworg);
  1048.  
  1049.     d = DotProduct (vpn, mirror_plane->normal);
  1050.     VectorMA (vpn, -2*d, mirror_plane->normal, vpn);
  1051.  
  1052.     r_refdef.viewangles[0] = -asin (vpn[2])/M_PI*180;
  1053.     r_refdef.viewangles[1] = atan2 (vpn[1], vpn[0])/M_PI*180;
  1054.     r_refdef.viewangles[2] = -r_refdef.viewangles[2];
  1055.  
  1056.     ent = &cl_entities[cl.viewentity];
  1057.     if (cl_numvisedicts < MAX_VISEDICTS)
  1058.     {
  1059.         cl_visedicts[cl_numvisedicts] = ent;
  1060.         cl_numvisedicts++;
  1061.     }
  1062.  
  1063.     gldepthmin = 0.5;
  1064.     gldepthmax = 1;
  1065.     glDepthRange (gldepthmin, gldepthmax);
  1066.     glDepthFunc (GL_LEQUAL);
  1067.  
  1068.     R_RenderScene ();
  1069.     R_DrawWaterSurfaces ();
  1070.  
  1071.     gldepthmin = 0;
  1072.     gldepthmax = 0.5;
  1073.     glDepthRange (gldepthmin, gldepthmax);
  1074.     glDepthFunc (GL_LEQUAL);
  1075.  
  1076.     // blend on top
  1077.     glEnable (GL_BLEND);
  1078.     glMatrixMode(GL_PROJECTION);
  1079.     if (mirror_plane->normal[2])
  1080.         glScalef (1,-1,1);
  1081.     else
  1082.         glScalef (-1,1,1);
  1083.     glCullFace(GL_FRONT);
  1084.     glMatrixMode(GL_MODELVIEW);
  1085.  
  1086.     glLoadMatrixf (r_base_world_matrix);
  1087.  
  1088.     glColor4f (1,1,1,r_mirroralpha.value);
  1089.     s = cl.worldmodel->textures[mirrortexturenum]->texturechain;
  1090.     for ( ; s ; s=s->texturechain)
  1091.         R_RenderBrushPoly (s);
  1092.     cl.worldmodel->textures[mirrortexturenum]->texturechain = NULL;
  1093.     glDisable (GL_BLEND);
  1094.     glColor4f (1,1,1,1);
  1095. }
  1096.  
  1097. /*
  1098. ================
  1099. R_RenderView
  1100.  
  1101. r_refdef must be set before the first call
  1102. ================
  1103. */
  1104. void R_RenderView (void)
  1105. {
  1106.     double    time1, time2;
  1107.     GLfloat colors[4] = {(GLfloat) 0.0, (GLfloat) 0.0, (GLfloat) 1, (GLfloat) 0.20};
  1108.  
  1109.     if (r_norefresh.value)
  1110.         return;
  1111.  
  1112.     if (!r_worldentity.model || !cl.worldmodel)
  1113.         Sys_Error ("R_RenderView: NULL worldmodel");
  1114.  
  1115.     if (r_speeds.value)
  1116.     {
  1117.         glFinish ();
  1118.         time1 = Sys_FloatTime ();
  1119.         c_brush_polys = 0;
  1120.         c_alias_polys = 0;
  1121.     }
  1122.  
  1123.     mirror = false;
  1124.  
  1125.     if (gl_finish.value)
  1126.         glFinish ();
  1127.  
  1128.     R_Clear ();
  1129.  
  1130.     // render normal view
  1131.  
  1132. /***** Experimental silly looking fog ******
  1133. ****** Use r_fullbright if you enable ******
  1134.     glFogi(GL_FOG_MODE, GL_LINEAR);
  1135.     glFogfv(GL_FOG_COLOR, colors);
  1136.     glFogf(GL_FOG_END, 512.0);
  1137.     glEnable(GL_FOG);
  1138. ********************************************/
  1139.  
  1140.     R_RenderScene ();
  1141.     R_DrawViewModel ();
  1142.     R_DrawWaterSurfaces ();
  1143.  
  1144. //  More fog right here :)
  1145. //    glDisable(GL_FOG);
  1146. //  End of all fog code...
  1147.  
  1148.     // render mirror view
  1149.     R_Mirror ();
  1150.  
  1151.     R_PolyBlend ();
  1152.  
  1153.     if (r_speeds.value)
  1154.     {
  1155. //        glFinish ();
  1156.         time2 = Sys_FloatTime ();
  1157.         Con_Printf ("%3i ms  %4i wpoly %4i epoly\n", (int)((time2-time1)*1000), c_brush_polys, c_alias_polys); 
  1158.     }
  1159. }
  1160.